import { AssetManager, Color, Component, Label, Node, Prefab, RichText, Scene, SceneAsset, SpriteFrame, Texture2D, _decorator, assetManager, color, director, log, sys, tween, v3 } from "cc";
import Banner, { BannerMode } from "./Banner";
import { UIManager } from "./UIManager";



const { ccclass, property } = _decorator;

/*** 所有 Bundle 包的名字，名字需要和包名保持一致 */
export enum Bundles {
    Mesh5 = "Mesh5",
    Mesh4 = "Mesh4",
    Mesh3 = "Mesh3",
    Mesh2 = "Mesh2",
    Mesh = "Mesh",
    Sprites = "Sprites",
    TieTu = "TieTu",
    Audio = "Audio"
}

export enum RemoteBundles { }

@ccclass()
export class BundleManager extends Component {
    @property(Node)
    HealthPanel: Node = null;
    @property(Node)
    PrivacyPanel: Node = null;
    private static _instance: any;
    public IsPrivacy: boolean = false;//同意隐私协议
    public BundleLoadingOver: boolean = false;//分包加载完毕
    public static get Instance(): BundleManager {
        if (BundleManager._instance == null) BundleManager._instance = new BundleManager();
        return BundleManager._instance;
    }
    public static PrivacyText: string = "";
    /*** Key: Bundle 名字   Value: Bundle */
    static BundleMap: Map<string, AssetManager.Bundle> = new Map<string, AssetManager.Bundle>();

    static LoadDone: boolean = false;//加载完毕

    start() {
        BundleManager.PrivacyText = `1.为了向您提供和持续优化定制化的服务，${Banner.Instance.Company}（以下简称“我们”）将收集和处理以下的信息：\n设备信息，包括设备标识符，Mac，机型，品牌，App包名，App版本号，设备分辨率及像素密度；网格信息，包括网格链接状态，接入网格的方式和类型，IP地址；\n使用信息，包括广告内容的展现，点击，下载；除上述信息外，我们还会收集您在本游戏的账号ID，以用来为您提供更加个性化的服务或广告。\n2，上述数据将会传输并保存至服务器，保存期限为60天，超出这一保留时间后将删除，但法律法规另有要求除外，我们保证不对外公开或向任何第三方提供您的个人信息，但是存在下列情形之一的除外：\n\t（1）公开或提供相关信息之前获得您的许可的；\n\t（2）根据法律或政策的规定而公开或提供的；\n\t（3）根据国家权力机关要求公开或提供的，\n如果你不同意我们采集上述信息，或不同意调用相关手机权限或功能，本软件将无法正常运行，您可通过卸载或退出本软件来终止数据收集及上传。\n3.如果您是未成年人，请在您的监护人仔细阅读本隐私政策。并在征得您的监护人同意的前提下使用我们的服务。\n4.如果您对本隐私政策和我们游戏有任何疑问和建议，请通过客服${"2291098720@qq.com"}联系我们，我们将尽快答复您。\n\n生效时间：2023年10月23日`;
        console.log("正在加载资源...");
        if (Banner.IS_ANDROID || Banner.Mode == BannerMode.测试包) {
            this.IsPrivacy = true;
        } else {
            let isPrivacy = sys.localStorage.getItem("Privacy");
            if (isPrivacy == "T") {
                this.IsPrivacy = true;
            } else {
                //弹出隐私公告
                this.PrivacyPanel.active = true;
                this.PrivacyPanel.getChildByName("ScrollView").getChildByName("view").getChildByName("content").getChildByName("PrivacyLabel")
                    .getComponent(Label).string = BundleManager.PrivacyText;
            }
        }
        this.LoadBundles();
    }

    //同意隐私协议
    PrivacyYesClick() {
        tween(this.PrivacyPanel)
            .to(0.3, { scale: v3(0, 0, 0) }, { easing: "backIn" })
            .start();
        sys.localStorage.setItem("Privacy", "T");
        this.IsPrivacy = true;
        this.SuccessCallback();
    }
    //拒绝
    PrivacyNoClick() {
        UIManager.HopHint("拒绝隐私无法进入游戏！");
    }


    SuccessCallback() {
        if (BundleManager.LoadDone && this.IsPrivacy == true) {
            this.scheduleOnce(() => { director.loadScene("MainPanel"); }, 1);
        }
    }

    LoadBundle(bunldename: string, CallBack: Function = null) {
        if (!BundleManager.BundleMap.has(bunldename)) {
            assetManager.loadBundle(bunldename, (err, bundle) => {
                if (err) {
                    console.error(`加载 Bundle 包：${name} 失败。`);
                    return;
                }
                console.log(bunldename + "分包加载成功！");
                BundleManager.BundleMap.set(bunldename, bundle);
                CallBack && CallBack();
            });
        } else {
            console.log("此分包已加载过，无需再次加载");
            CallBack && CallBack();
        }
    }

    LoadBundles() {
        const bundleNames = BundleManager.GetEnumValues(Bundles);
        const bundlePromises = bundleNames.map(name => {
            return new Promise((resolve, reject) => {
                assetManager.loadBundle(name, (err, bundle) => {
                    if (err) {
                        reject([name, err]);
                    } else {
                        resolve(bundle);
                    }
                });
            });
        });
        Promise.all(bundlePromises)
            .then((bundles: AssetManager.Bundle[]) => {
                for (let i = 0; i < bundles.length; i++) {
                    if (!BundleManager.BundleMap.has(bundles[i].name) || BundleManager.BundleMap.get(bundles[i].name) != bundles[i]) {
                        BundleManager.BundleMap.set(bundles[i].name, bundles[i]);
                        console.log(`加载本地 Bundle: ${bundles[i].name} 成功`);
                    }
                }
                console.log("加载资源成功");
                BundleManager.LoadDone = true;
                this.SuccessCallback();
            })
            .catch(error => {
                console.log("加载资源失败", 10);
                console.error(`加载本地 Bundle:${error[0]} 失败:[${error[1]}]`);
            });
    }

    //加载远程包无论成功失败都进入游戏
    LoadRemoteBundles(callback: Function = null) {
        const bundleNames = BundleManager.GetEnumValues(RemoteBundles);
        const bundlePromises = bundleNames.map(name => {
            return new Promise((resolve, reject) => {
                assetManager.loadBundle(name, (err, bundle) => {
                    if (err) {
                        reject([name, err]);
                    } else {
                        resolve(bundle);
                    }
                });
            });
        });

        Promise.all(bundlePromises)
            .then((bundles: AssetManager.Bundle[]) => {
                for (let i = 0; i < bundles.length; i++) {
                    if (!BundleManager.BundleMap.has(bundles[i].name) || BundleManager.BundleMap.get(bundles[i].name) != bundles[i]) {
                        BundleManager.BundleMap.set(bundles[i].name, bundles[i]);
                        console.log(`加载远程 Bundle: ${bundles[i].name} 成功`);
                    }
                }
                callback && callback();
            })
            .catch(error => {
                callback && callback();
                console.log("加载资源失败...", 10);
                console.error(`加载远程 Bundle:${error[0]} 失败:[${error[1]}]`);
            });
    }

    /*** 设置 Bundle 包 */
    public static SetBundle(name: string, cb: Function = null) {
        assetManager.loadBundle(name, (err, bundle) => {
            if (err) {
                console.error(`加载 Bundle 包：${name} 失败。`);
                return;
            }
            BundleManager.BundleMap.set(name, bundle);
            cb && cb();
        });
    }

    /*** 获取 Bundle 包 */
    public static GetBundle(bundle: string) {
        if (this.CheckBundleIsNull(bundle)) return;
        return this.BundleMap.get(bundle);
    }

    /*** 加载 Bundle 包内资源 */
    public static Load(bundle: string, path: string, type: any, cb: Function = () => { }) {
        if (this.CheckBundleIsNull(bundle)) return;
        this.BundleMap.get(bundle).load(path, type, (err: any, res: any) => {
            if (err) {
                console.error(err.message || err);
                cb(err, res);
                return;
            }

            cb && cb(null, res);
        })
    }

    /*** 加载 Bundle 包内场景 */
    public static LoadBundleScene(bundle: string, scene: string) {
        if (this.CheckBundleIsNull(bundle)) return;
        this.BundleMap.get(bundle).loadScene(scene, Scene, (err, scene) => {
            if (err) {
                console.error(`加载 Bundle: ${bundle} 场景失败: ${scene}`);
                return;
            }

            director.runScene(scene);
        });
    }

    /*** 加载 Bundle 包内预制体 */
    public static LoadPrefab(bundle: string, path: string) {
        if (this.CheckBundleIsNull(bundle)) return;
        return new Promise((resolve, reject) => {
            this.Load(bundle, `${path}`, Prefab, (err: any, prefab: Prefab) => {
                if (err) {
                    console.error(`加载 Bundle: ${bundle} cc.Prefab 加载失败 Path: ${path}`);
                    reject && reject();
                    return;
                }

                resolve && resolve(prefab);
            });
        });
    }

    /*** 加载 Bundle 包内 cc.SpriteFrame */
    public static LoadSpriteFrame(bundle: string, path: string) {
        if (this.CheckBundleIsNull(bundle)) return;
        return new Promise((resolve, reject) => {
            this.Load(bundle, `${path}/spriteFrame`, SpriteFrame, (err: any, spriteFrame: SpriteFrame) => {
                if (err) {
                    console.error(`加载 Bundle: ${bundle} cc.SpriteFrame 加载失败 Path: ${path}`);
                    reject && reject();
                    return;
                }

                resolve && resolve(spriteFrame);
            });
        });
    }

    /*** 加载 Bundle 包内 cc.Texture2D */
    public static LoadTexture(bundle: string, path: string) {
        if (this.CheckBundleIsNull(bundle)) return;
        return new Promise((resolve, reject) => {
            this.Load(bundle, `${path}`, Texture2D, (err: any, texture: Texture2D) => {
                if (err) {
                    console.error(`加载 Bundle: ${bundle} cc.Texture2D 加载失败 Path: ${path}`);
                    reject && reject();
                    return;
                }

                resolve && resolve(texture);
            });
        });
    }

    /*** 检查 Bunle 包是否为空，可以特殊处理，请求用户连接网络重启游戏 */
    private static CheckBundleIsNull(bundle: string): boolean {
        if (!this.BundleMap.has(bundle)) {
            console.error(`不存在此 Bundle: ${bundle}，请检查 Bundle 名称或者网络`);
            return true;
        }
        return false;
    }

    public static GetEnumValues(enumType: any): string[] {
        const enumValues = Object.keys(enumType)
            .map(key => enumType[key])
            .filter(value => typeof value === 'string');

        return enumValues as string[];
    }
}